package com.infore.dataAudit.controller;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.activiti.bpmn.converter.BpmnXMLConverter;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.editor.constants.ModelDataJsonConstants;
import org.activiti.editor.language.json.converter.BpmnJsonConverter;
import org.activiti.engine.ActivitiObjectNotFoundException;
import org.activiti.engine.HistoryService;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.repository.Model;
import org.apache.commons.io.IOUtils;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.infore.dataAudit.enums.ResultStatus;
import com.infore.dataAudit.service.DeployService;
import com.infore.dataAudit.service.RunningTimeService;
import com.infore.dataAudit.util.ResultEntity;





/**
 * 
 * @author cys
 * 流程部署编辑控制接口层 公开
 */
@RestController
@RequestMapping("/deploy")
public class DeployController {
    @Resource
    private DeployService deployService;
    @Resource
    private RepositoryService repositoryService;
    @Resource
    private RuntimeService runtimeService;
    @Resource
    private RunningTimeService runningTimeService;
    @Resource
    private TaskService taskService;
    @Resource
    private HistoryService historyService;
    @Resource
    private ObjectMapper objectMapper;
    
   /**
    * 部署一个流程 添加一个部署文件
    * 
    * @author 蔡永顺
    * @return ResultEntity
    * @param deployFile
    * @return
    * @throws IOException
    * @date 2019年2月28日下午3:29:16
    */
    @ResponseBody
    @RequestMapping(value = "/addDeploy", method = {RequestMethod.GET, RequestMethod.POST})
    public ResultEntity addDeploy(@RequestParam(required = true)MultipartFile deployFile) throws IOException {
        return deployService.addDeploy(deployFile);
    }
    
    /**
     * 完全删除总个流程部署 包含总个流程实例 任务
     *  删除包括running process及history process
     * @author 蔡永顺
     * @return ResultEntity
     * @param fileNames
     * @return
     * @date 2019年2月28日下午3:37:05
     */
    @ResponseBody
    @RequestMapping(value = "/delDeploy", method = {RequestMethod.GET, RequestMethod.POST})
    public ResultEntity delDeploy(@RequestParam(required = true)String fileNames) {
        if (fileNames == null || fileNames.trim().isEmpty()) {
            return null;
        }
        try {
            return deployService.delDeploy(fileNames);
        } catch (ActivitiObjectNotFoundException e) {
            e.printStackTrace();
            return  new ResultEntity(ResultStatus.ERROR, e.getMessage());
        }
    }
    
    /**
     * 分页查询部署的文件信息
     * 
     * @param deployId
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "/queryDeploy", method = {RequestMethod.GET, RequestMethod.POST})
    public ResultEntity queryDeploy(@RequestParam(required = true)String deployName, 
            @RequestParam(required = true)Integer pageSize, 
            @RequestParam(required = true)Integer page) {
        Map<String, Object> data = deployService.queryDeployByPage(deployName, pageSize, page);
        if (data == null) {
            return new ResultEntity(ResultStatus.ERROR, "");
        }
        return new ResultEntity(ResultStatus.SUCCESS, "成功");
    }

    /**
     * 在编辑器中新建一个流程
     * 
     * @author 蔡永顺
     * @return void
     * @param request
     * @param response
     * @date 2018年1月2日上午8:51:38
     */
    @ResponseBody
    @SuppressWarnings("deprecation")
    @RequestMapping(value = "create", method = {RequestMethod.GET, RequestMethod.POST})
    public ResultEntity create(@RequestParam("name") String name, @RequestParam("key") String key,
            @RequestParam("description") String description, @RequestParam("category") String category,
            HttpServletRequest request, HttpServletResponse response) {
        if (name == null || name.trim().isEmpty() || key == null || key.trim().isEmpty()) {
            return new ResultEntity(ResultStatus.ERROR,  "流程name与key不能为空");
        }
        try {
            ObjectNode editorNode = objectMapper.createObjectNode();
            editorNode.put("id", "canvas");
            editorNode.put("resourceId", "canvas");
            ObjectNode stencilSetNode = objectMapper.createObjectNode();
            stencilSetNode.put("namespace", "http://b3mn.org/stencilset/bpmn2.0#");
            editorNode.put("stencilset", stencilSetNode);
            Model modelData = repositoryService.newModel();

            ObjectNode modelObjectNode = objectMapper.createObjectNode();
            modelObjectNode.put(ModelDataJsonConstants.MODEL_NAME, name);
            modelObjectNode.put(ModelDataJsonConstants.MODEL_REVISION, 1); // 版本默认从1开始
            modelObjectNode.put(ModelDataJsonConstants.MODEL_DESCRIPTION, description);
            modelData.setMetaInfo(modelObjectNode.toString());
            modelData.setName(name);
            modelData.setKey(key);

            // 保存模型
            repositoryService.saveModel(modelData);
            repositoryService.addModelEditorSource(modelData.getId(), editorNode.toString().getBytes("utf-8"));
            // response.sendRedirect(request.getContextPath() +
            // "/modeler.html?modelId=" + modelData.getId());
            return new ResultEntity(ResultStatus.SUCCESS, "成功").setInfo(modelData.getId());
        } catch (Exception e) {
            return new ResultEntity(ResultStatus.ERROR,  "创建模型失败：" + e.getMessage());
        }
    }

    /**
     * 获取所有模型列表
     * 
     * @author 蔡永顺
     * @return ResultUtil
     * @date 2018年1月2日上午10:20:12
     */
    @RequestMapping(value = "list", method = {RequestMethod.GET, RequestMethod.POST})
    @ResponseBody
    public ResultEntity modelList() {
        List<Model> list = repositoryService.createModelQuery().list();
        return new ResultEntity(ResultStatus.SUCCESS, "成功").setDataList(list);
    }

    /**
     * 根据modelId部署流程
     * 
     * @author 蔡永顺
     * @return String
     * @param modelId
     * @date 2018年1月2日上午10:22:49
     */
    @RequestMapping(value = "deploy/{modelId}", method = {RequestMethod.GET, RequestMethod.POST})
    @ResponseBody
    public ResultEntity deploy(@PathVariable("modelId") String modelId) {
        try {
            Model modelData = repositoryService.getModel(modelId);
            ObjectNode modelNode = (ObjectNode) objectMapper
                    .readTree(repositoryService.getModelEditorSource(modelData.getId()));
            String key = modelData.getKey();
            if (key == null) {
                key = modelData.getName();
            }
            byte[] bpmnBytes = null;

            BpmnModel model = new BpmnJsonConverter().convertToBpmnModel(modelNode);
            bpmnBytes = new BpmnXMLConverter().convertToXML(model);
            String processName = modelData.getName() + ".bpmn20.xml";
            repositoryService.createDeployment().name(modelData.getName())
                    .addString(processName, new String(bpmnBytes)).deploy();
        } catch (Exception e) {
            //LOGGER.error("根据模型部署流程失败：modelId={}", modelId, e);
            return new ResultEntity(ResultStatus.ERROR,  "流程部署失败: " + e.getMessage());
        }
        return new ResultEntity(ResultStatus.SUCCESS, "部署成功");
    }

    /**
     * 导出model的xml文件
     */
    @RequestMapping(value = "/export/{modelId}", method = {RequestMethod.GET, RequestMethod.POST})
    public void export(@PathVariable("modelId") String modelId, HttpServletResponse response) {
        ByteArrayInputStream in = null;
        try {
            Model modelData = repositoryService.getModel(modelId);
            BpmnJsonConverter jsonConverter = new BpmnJsonConverter();
            JsonNode editorNode = new ObjectMapper()
                    .readTree(repositoryService.getModelEditorSource(modelData.getId()));
            BpmnModel bpmnModel = jsonConverter.convertToBpmnModel(editorNode);
            BpmnXMLConverter xmlConverter = new BpmnXMLConverter();
            byte[] bpmnBytes = xmlConverter.convertToXML(bpmnModel);

            in = new ByteArrayInputStream(bpmnBytes);
            IOUtils.copy(in, response.getOutputStream());
            String filename = bpmnModel.getMainProcess().getId() + ".bpmn20.xml";
            response.setHeader("Content-Disposition", "attachment; filename=" + filename);
            response.flushBuffer();
        } catch (Exception e) {
            //LOGGER.error("导出model的xml文件失败：modelId={}", modelId, e);
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e) {
                   // LOGGER.error("流关闭失败", e);
                }
            }
        }
    }

    /**
     * 删除流程
     * 
     * @author 蔡永顺
     * @return ResultUtil
     * @param modelId
     * @date 2018年1月31日下午3:11:35
     */
    @RequestMapping(value = "delete/{modelId}", method = {RequestMethod.GET, RequestMethod.POST})
    @ResponseBody
    public ResultEntity delete(@PathVariable("modelId") String modelId) {
        repositoryService.deleteModel(modelId);
        return new ResultEntity(ResultStatus.SUCCESS, "删除成功");
    }

    /**
     * 生成部署流程的流程图
     * 
     * @author cys
     * @return ResultUtil
     * @param deployKey
     * @throws IOException
     * @date 2018年3月19日上午11:17:55
     */
    @RequestMapping(value = "getDeployPng", method = {RequestMethod.GET, RequestMethod.POST})
    @ResponseBody
    public ResultEntity getDeployPNG(HttpServletResponse response, @RequestParam(required = true)String deployKey) throws IOException {
        response.setContentType("image/jpeg");
        InputStream is = null;
        try {
            is = runningTimeService.generateDiagramByDeployKey(deployKey);
            ServletOutputStream os = response.getOutputStream();
            byte[] bytes = new byte[1024];
            int length = -1;
            while ((length = is.read(bytes)) != -1) {
                os.write(bytes, 0, length);
            }
            response.flushBuffer();
        } finally {
            if (is != null) {
                is.close();
            }
        }
        return new ResultEntity(ResultStatus.SUCCESS, "成功");
    }
    
    
}
